package com.zmn.oms.business.impl.part;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.part.OrderPartBService;
import com.zmn.oms.business.interfaces.work.OrderWorkAmountBService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MathUtil;
import com.zmn.oms.model.dto.part.*;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.part.OrderPart;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.part.OrderPartService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.scm2.common.model.dio.scm.maintenance.order.use.MaintenanceOrderUseDIO;
import com.zmn.scm2.common.model.dio.scm.maintenance.order.use.item.MaintenanceOrderUseItemDIO;
import com.zmn.scm2.common.model.dio.scm.monitor.OrderGoodsDIO;
import com.zmn.scm2.common.model.dro.scm.monitor.CheckOrderDRO;
import com.zmn.scm2.dubbo.interfaces.scm.engineer.purchase.EngineerPurchaseModifyRemoteService;
import com.zmn.scm2.dubbo.interfaces.scm.maintenance.order.use.MaintenanceOrderUseListRemoteService;
import com.zmn.scm2.dubbo.interfaces.scm.maintenance.order.use.MaintenanceOrderUseModifyRemoteService;
import com.zmn.scm2.dubbo.interfaces.scm.monitor.ScmMonitorWarnListRemoteService;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 类描述：工单配件业务实现类
 *
 * @author heciqi
 * @date 2018/11/28 15:19
 */
@Service
public class OrderPartBServiceImpl implements OrderPartBService {

    private final static Logger logger = LoggerFactory.getLogger(OrderPartBServiceImpl.class);

    @Autowired
    private OrderPartService orderPartService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderLogBService orderLogBService;

    @Autowired
    private OrderWorkAmountBService orderWorkAmountBService;

    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false, timeout = 15000)
    private MaintenanceOrderUseModifyRemoteService maintenanceOrderUseModifyRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false, timeout = 15000)
    private MaintenanceOrderUseListRemoteService maintenanceOrderUseListRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false, timeout = 15000)
    private EngineerPurchaseModifyRemoteService engineerPurchaseModifyRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private ScmMonitorWarnListRemoteService scmMonitorWarnListRemoteService;

    /**
     * 根据工单id查询
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderPartDTO listByOrderId(Long orderId) {
        OrderPartDTO orderPartDTO = new OrderPartDTO();

        List<OrderPart> orderParts = orderPartService.listByOrderIdSrcMaster(orderId);
        if (orderParts.isEmpty()) {
            return orderPartDTO;
        }

        // 内报
        List<OrderPart> inParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_SOURCING_IN)).collect(Collectors.toList());
        // 内报工程师分组
        Map<Integer, List<OrderPart>> inPartsCollect = inParts.stream().collect(Collectors.groupingBy(OrderPart::getMasterId));
        List<OrderPartMasterDTO> inPartsDTO = Lists.newArrayList();
        inPartsCollect.forEach((k, v) -> {
            OrderPartMasterDTO masterDTO = new OrderPartMasterDTO();
            masterDTO.setMasterId(k);
            masterDTO.setOrderParts(v);
            inPartsDTO.add(masterDTO);
        });

        // 外报
        List<OrderPart> outParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_SOURCING_OUT)).collect(Collectors.toList());
        // 外报工程师分组
        Map<Integer, List<OrderPart>> outPartsCollect = outParts.stream().collect(Collectors.groupingBy(OrderPart::getMasterId));
        List<OrderPartMasterDTO> outPartsDTO = Lists.newArrayList();
        inPartsCollect.forEach((k, v) -> {
            OrderPartMasterDTO masterDTO = new OrderPartMasterDTO();
            masterDTO.setMasterId(k);
            masterDTO.setOrderParts(v);
            outPartsDTO.add(masterDTO);
        });

        // 运杂
        List<OrderPart> deliverParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_DELIVER)).collect(Collectors.toList());
        // 运杂工程师分组
        Map<Integer, List<OrderPart>> deliverPartsCollect = deliverParts.stream().collect(Collectors.groupingBy(OrderPart::getMasterId));
        List<OrderPartMasterDTO> deliverPartsDTO = Lists.newArrayList();
        inPartsCollect.forEach((k, v) -> {
            OrderPartMasterDTO masterDTO = new OrderPartMasterDTO();
            masterDTO.setMasterId(k);
            masterDTO.setOrderParts(v);
            deliverPartsDTO.add(masterDTO);
        });

        orderPartDTO.setInParts(inPartsDTO);
        orderPartDTO.setOutParts(outPartsDTO);
        orderPartDTO.setDeliverParts(deliverPartsDTO);

        return orderPartDTO;
    }

    /**
     * 根据工单id，工程师id查询
     *
     * @param orderId
     * @param masterId
     * @return
     */
    @Override
    public SingleMasterOrderPartDTO listByOrderIdAndMaster(Long orderId, Integer masterId) {
        SingleMasterOrderPartDTO singleMasterOrderPartDTO = new SingleMasterOrderPartDTO();

        List<OrderPart> orderParts = orderPartService.listByOrderIdAndMasterId(orderId, masterId);
        if (orderParts.isEmpty()) {
            return singleMasterOrderPartDTO;
        }

        // 内报
        List<OrderPart> inParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_SOURCING_IN)).collect(Collectors.toList());
        // 外报
        List<OrderPart> outParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_SOURCING_OUT)).collect(Collectors.toList());
        // 订单杂项费用
        List<OrderPart> deliverParts = orderParts.stream().filter((e) -> e.getPartType().equals(OrderConsts.PART_TYPE_DELIVER)).collect(Collectors.toList());

        singleMasterOrderPartDTO.setInParts(inParts);
        singleMasterOrderPartDTO.setOutParts(outParts);
        singleMasterOrderPartDTO.setDeliverParts(deliverParts);

        return singleMasterOrderPartDTO;
    }

    /**
     * 新增内采配件
     *
     * @param addOrderPartDTO
     */
    @Override
    public void insertInOrderPart(AddOrderPartDTO addOrderPartDTO) throws OmsBaseException {

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(addOrderPartDTO.getOrderId(), addOrderPartDTO.getWorkId());

        List<OrderPart> list = addOrderPartDTO.getParts();
        // 1，删除工单配件
        orderPartService.deleteByOrderIdAndPartType(addOrderPartDTO.getOrderId(), OrderConsts.PART_TYPE_SOURCING_IN);

        list.forEach(orderPart -> {
            orderPart.setReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_NONE);
        });

        // 2，新增工单配件
        if (!list.isEmpty()) {
            orderPartService.insertAll(list);
        }

        // 3，计算配件金额
        // 内采配件
        int inSourcingAmount = list.stream().mapToInt((e) -> MathUtil.amountMultiplyNumber(e.getPrice(), e.getNumber())).sum();

        // 配件总金额
        Integer outSourcingAmount = Optional.ofNullable(dbOrderWork.getOutSourcingAmount()).orElse(0);
        Integer deliverAmount = Optional.ofNullable(dbOrderWork.getDeliverAmount()).orElse(0);
        Integer fcPartAmount = Optional.ofNullable(dbOrderWork.getFactoryPartAmount()).orElse(0);
        int partAmount = inSourcingAmount + outSourcingAmount + deliverAmount + fcPartAmount;

        // 4，更新工单金额
        OrderWork orderWork = new OrderWork();
        if (partAmount == 0) {
            orderWork.setPartUse(GlobalConsts.NO);
            orderWork.setPartRetain(GlobalConsts.NONE);
        } else {
            orderWork.setPartUse(GlobalConsts.YES);
        }
        if ((outSourcingAmount + deliverAmount) == 0) {
            orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_NONE);
        }
        orderWork.setOrderId(addOrderPartDTO.getOrderId());
        orderWork.setWorkId(addOrderPartDTO.getWorkId());
        orderWork.setPartAmount(partAmount);
        orderWork.setInSourcingAmount(inSourcingAmount);
        orderWork.setOutSourcingAmount(dbOrderWork.getOutSourcingAmount());
        orderWork.setDeliverAmount(dbOrderWork.getDeliverAmount());
        orderWorkAmountBService.updatePartAmount(orderWork);

        // 4，调用SCM接口
        this.scmOrderPartUsed(dbOrderWork.getPlatWork(), addOrderPartDTO);
    }

    private void scmOrderPartUsed(Integer platWork, AddOrderPartDTO addOrderPartDTO) throws OmsBaseException {
        List<OrderPart> list = addOrderPartDTO.getParts();

        List<MaintenanceOrderUseItemDIO> skuDIOList = Lists.newArrayList();
        MaintenanceOrderUseDIO dio = new MaintenanceOrderUseDIO();
        dio.setWorkId(addOrderPartDTO.getWorkId());
        dio.setPlat(platWork);
        dio.setStatus(GlobalConsts.NO);
        dio.setOperatorId(addOrderPartDTO.getOperatorId());
        dio.setOperator(addOrderPartDTO.getOperator());
        dio.setGoodsTypes(OrderConsts.PART_TYPE_SOURCING_IN);

        // 如果核配件保存配件列表为null，则清除工程师库存。
        if (CollectionUtil.isNullOrEmpty(list)) {
            dio.setType(GlobalConsts.YES);
            logger.info("新增020订单使用配件入参:[{}]", JSON.toJSONString(dio));
            ResponseDTO response = maintenanceOrderUseModifyRemoteService.addMaintenanceOrderUse(dio);
            logger.info("新增020订单使用配件出参:[{}]", JSON.toJSONString(response));
            if (!response.isSuccess()) {
                throw new OmsBaseException(response.getStatus(), "工程师库存退回失败：订单号" + addOrderPartDTO.getOrderId());
            }
        } else {

            list.forEach(p -> {
                MaintenanceOrderUseItemDIO itemDIO = new MaintenanceOrderUseItemDIO();
                itemDIO.setSaleOrderId(p.getDrawId());
                itemDIO.setMasterId(p.getMasterId());
                itemDIO.setMasterName(p.getMasterName());
                itemDIO.setGoodsId(p.getPartId());
                itemDIO.setGoodsName(p.getPartName());
                itemDIO.setCategOneId(p.getCategOneId());
                itemDIO.setCategTwoId(p.getCategId());
                itemDIO.setCategOneName(p.getCategOneName());
                itemDIO.setCategTwoName(p.getCategName());
                itemDIO.setNumber(p.getNumber());
                itemDIO.setUnitName(p.getUnit());
                itemDIO.setSourceType(OrderConsts.PART_TYPE_SOURCING_IN);
                itemDIO.setPoPrice(p.getPurchasePrice());
                itemDIO.setSalePrice(p.getPrice());
                itemDIO.setImgSrc(p.getComparisonImgSrc());// 内采配件同步到SCM2新旧配件对比照，然后由SCM2同步检测结果给oms
                skuDIOList.add(itemDIO);
            });

            dio.setType(GlobalConsts.NO);
            dio.setGoodsList(skuDIOList);

            logger.info("新增020订单使用配件入参:[{}]", JSON.toJSONString(dio));
            com.zmn.common.dto2.ResponseDTO responseDTO =
                    maintenanceOrderUseModifyRemoteService.addMaintenanceOrderUse(dio);
            logger.info("新增020订单使用配件出参:[{}]", JSON.toJSONString(responseDTO));
            if (!responseDTO.isSuccess()) {
                logger.error(responseDTO.getMessage());
                throw new OmsBaseException(responseDTO.getStatus(), "工程师库存扣除失败：订单号" + addOrderPartDTO.getOrderId());
            }
        }
    }

    /**
     * 新增外报配件
     *
     * @param addOrderPartDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_PART_ADD_REIMBURSE)
    public void insertOutOrderPart(AddOrderPartDTO addOrderPartDTO) throws OmsBaseException {
        Long orderId = addOrderPartDTO.getOrderId();
        Long workId = addOrderPartDTO.getOrderId();

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);

        // 已派单&已领单&已上门&服务完成&已完成-进行中 不能增加外报和运杂
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT,
                OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE, OrderStatusConsts.WORK_STATUS_COMPLETE);
        boolean statusSupport = supportStatusList.contains(dbOrderWork.getStatus());
        if (!(statusSupport && Objects.equals(OrderStatusConsts.WORK_RESULT_DOING, dbOrderWork.getResultStatus()))) {
            throw new OmsBaseException("工单已收单不能新增外报");
        }

        List<OrderPart> list = addOrderPartDTO.getParts();
        list.forEach(e -> {
            e.setOrderId(orderId);
            e.setReimburse(GlobalConsts.YES);
            e.setReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_DOING);
            e.setCostPrice(Optional.ofNullable(e.getCostPrice()).orElse(e.getPrice()));//为空 配件销售总额=配件综合成本总额
            e.setPurchasePrice(Optional.ofNullable(e.getPurchasePrice()).orElse(e.getPrice()));//为空 配件采购总额=配件综合成本总额
        });

        // 查询所有外报，将老仓储过滤，只保留新仓储外报
        List<OrderPart> oldList = orderPartService.listByOrderIdSrcMaster(orderId, OrderConsts.PART_TYPE_SOURCING_OUT);
        List<OrderPart> newList = oldList.stream().filter(part -> Objects.nonNull(part.getReimburseId()))
                .collect(Collectors.toList());
        list.addAll(newList);

        // 1，删除工单配件
        orderPartService.deleteByOrderIdAndPartType(orderId, OrderConsts.PART_TYPE_SOURCING_OUT);

        // 2，新增工单配件
        if (!list.isEmpty()) {
            orderPartService.insertAll(list);
        }

        // 3，计算配件金额
        // 外报
        int outSourcingAmount = list.stream().mapToInt((e) -> MathUtil.amountMultiplyNumber(e.getPrice(), e.getNumber())).sum();
        // 内采
        Integer inSourcingAmount = Optional.ofNullable(dbOrderWork.getInSourcingAmount()).orElse(0);
        // 运杂
        Integer deliverAmount = Optional.ofNullable(dbOrderWork.getDeliverAmount()).orElse(0);
        // 厂商配件
        Integer fcPartAmount = Optional.ofNullable(dbOrderWork.getFactoryPartAmount()).orElse(0);
        // 总金额
        int partAmount = outSourcingAmount + inSourcingAmount + deliverAmount + fcPartAmount;

        // 4，更新工单金额
        OrderWork orderWork = new OrderWork();
        orderWork.setOrderId(orderId);
        orderWork.setWorkId(workId);
        if (partAmount == 0) {
            orderWork.setPartUse(GlobalConsts.NO);
        } else {
            orderWork.setPartUse(GlobalConsts.YES);
        }
        orderWork.setPartRetain(GlobalConsts.NONE);
        orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_DOING);
        orderWork.setPartReimburse(GlobalConsts.YES);
        orderWork.setPartReimburseAmount(deliverAmount + outSourcingAmount);
        orderWork.setPartAmount(partAmount);
        orderWork.setOutSourcingAmount(outSourcingAmount);
        orderWork.setInSourcingAmount(inSourcingAmount);
        orderWork.setDeliverAmount(deliverAmount);
        orderWorkAmountBService.updatePartAmount(orderWork);
    }

    /**
     * 新增订单杂项费用
     *
     * @param addOrderPartDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_PART_ADD_REIMBURSE)
    public void insertDeliverOrderPart(AddOrderPartDTO addOrderPartDTO) throws OmsBaseException {
        Long orderId = addOrderPartDTO.getOrderId();
        Long workId = addOrderPartDTO.getOrderId();

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);

        // 已派单&已领单&已上门&服务完成&已完成-进行中 不能增加外报和运杂
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT,
                OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE, OrderStatusConsts.WORK_STATUS_COMPLETE);
        boolean statusSupport = supportStatusList.contains(dbOrderWork.getStatus());
        if (!(statusSupport && Objects.equals(OrderStatusConsts.WORK_RESULT_DOING, dbOrderWork.getResultStatus()))) {
            throw new OmsBaseException("工单已收单不能新增运杂");
        }

        List<OrderPart> list = addOrderPartDTO.getParts();
        // 如果报销工程师与工单工程师不一致，则不记录
        if (!Objects.equals(dbOrderWork.getMasterId(), list.get(0).getMasterId())) {
            logger.info("工单工程师id与报销工程师id不一致，工单号:{}，工单工程师id:{}，报销工程师id:{}", dbOrderWork.getOrderId(),
                    dbOrderWork.getMasterId(), list.get(0).getMasterId());
            return;
        }

        list.forEach(e -> {
            e.setOrderId(orderId);
            e.setReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_DOING);
            e.setReimburse(GlobalConsts.YES);
        });

        // 查询所有运杂，将老仓储过滤，只保留新仓储运杂
        List<OrderPart> oldList = orderPartService.listByOrderIdSrcMaster(orderId, OrderConsts.PART_TYPE_DELIVER);
        List<OrderPart> newList = oldList.stream().filter(part -> Objects.nonNull(part.getReimburseId()))
                .collect(Collectors.toList());
        list.addAll(newList);

        // 1，删除工单配件
        orderPartService.deleteByOrderIdAndPartType(orderId, OrderConsts.PART_TYPE_DELIVER);

        // 2，新增工单配件
        if (!list.isEmpty()) {
            orderPartService.insertAll(list);
        }

        // 3，计算配件金额
        // 运杂
        int deliverAmount = list.stream().mapToInt((e) -> MathUtil.amountMultiplyNumber(e.getPrice(), e.getNumber())).sum();
        // 内采
        Integer inSourcingAmount = Optional.ofNullable(dbOrderWork.getInSourcingAmount()).orElse(0);
        // 外报
        Integer outSourcingAmount = Optional.ofNullable(dbOrderWork.getOutSourcingAmount()).orElse(0);
        // 厂商配件
        Integer fcPartAmount = Optional.ofNullable(dbOrderWork.getFactoryPartAmount()).orElse(0);
        // 总金额
        int partAmount = deliverAmount + inSourcingAmount + outSourcingAmount + fcPartAmount;

        // 4，更新工单金额
        OrderWork orderWork = new OrderWork();
        orderWork.setOrderId(orderId);
        orderWork.setWorkId(workId);
        if (partAmount == 0) {
            orderWork.setPartUse(GlobalConsts.NO);
        } else {
            orderWork.setPartUse(GlobalConsts.YES);
        }
        orderWork.setPartRetain(GlobalConsts.NONE);
        orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_DOING);
        orderWork.setPartReimburse(GlobalConsts.YES);
        orderWork.setPartReimburseAmount(deliverAmount + outSourcingAmount);
        orderWork.setPartAmount(partAmount);
        orderWork.setInSourcingAmount(dbOrderWork.getInSourcingAmount());
        orderWork.setOutSourcingAmount(dbOrderWork.getOutSourcingAmount());
        orderWork.setDeliverAmount(deliverAmount);
        orderWorkAmountBService.updatePartAmount(orderWork);
    }

    /**
     * 新增厂商配件
     *
     * @param addOrderPartDTO
     */
    @Override
    public void insertFactoryOrderPart(AddOrderPartDTO addOrderPartDTO) {
        Long orderId = addOrderPartDTO.getOrderId();
        Long workId = addOrderPartDTO.getOrderId();

        List<OrderPart> list = addOrderPartDTO.getParts();
        list.forEach(e -> {
            e.setOrderId(orderId);
            e.setReimburse(GlobalConsts.NO);
            e.setPartType(OrderConsts.PART_TYPE_FACTORY);
        });

        // 1，删除工单配件
        orderPartService.deleteByOrderIdAndPartType(orderId, OrderConsts.PART_TYPE_FACTORY);

        // 2，新增工单配件
        if (!list.isEmpty()) {
            orderPartService.insertAll(list);
        }

        // 3，计算配件金额
        // 厂商配件
        /*int fcPartAmount = list.stream().mapToInt((e) -> e.getNumber() * e.getPrice()).sum();

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        // 内采
        Integer inSourcingAmount = Optional.ofNullable(dbOrderWork.getInSourcingAmount()).orElse(0);
        // 外报
        Integer outSourcingAmount = Optional.ofNullable(dbOrderWork.getOutSourcingAmount()).orElse(0);
        // 运杂
        Integer deliverAmount = Optional.ofNullable(dbOrderWork.getDeliverAmount()).orElse(0);
        // 总金额
        int partAmount = deliverAmount + inSourcingAmount + outSourcingAmount + fcPartAmount;

        // 4，更新工单金额
        OrderWork orderWork = new OrderWork();
        orderWork.setOrderId(orderId);
        orderWork.setWorkId(workId);
        if (partAmount == 0) {
            orderWork.setPartUse(GlobalConsts.NO);
        } else {
            orderWork.setPartUse(GlobalConsts.YES);
        }
        orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_NONE);
        orderWork.setPartReimburse(GlobalConsts.NO);
        orderWork.setPartAmount(partAmount);
        orderWork.setFactoryPartAmount(fcPartAmount);
        orderWorkAmountBService.updatePartAmount(orderWork);*/
    }


    /**
     * 清空工单配件（工单配件，退回工程师库房，更新工单金额）
     *
     * @param orderId
     */
    @Override
    public void clearOrderPart(Long orderId, Long operatorId, String operator) throws OmsBaseException {

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        // 1, 设置申请中的运杂和外报为取消
        logger.info("删除工单下的所有外报和运杂入参:[{}]", orderId);
        ResponseDTO<Integer> responseDTO = engineerPurchaseModifyRemoteService.deleteBySourceId(String.valueOf(orderId));
        logger.info("删除工单下的所有外报和运杂出参:[{}]", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException("供应链服务：" + responseDTO.getMessage());
        }

        MaintenanceOrderUseDIO dio = new MaintenanceOrderUseDIO();
        dio.setWorkId(dbOrderWork.getWorkId());
        dio.setPlat(dbOrderWork.getPlatWork());
        dio.setStatus(GlobalConsts.NO);
        dio.setType(GlobalConsts.YES);
        dio.setGoodsTypes(OrderConsts.PART_TYPE_SOURCING_IN);
        dio.setOperator(operator);
        dio.setOperatorId(operatorId);

        // 防止oms-api服务没有传操作者信息
        if (Objects.isNull(dio.getOperatorId())) {
            dio.setOperatorId(1L);
        }
        if (Objects.isNull(dio.getOperator())) {
            dio.setOperator("系统");
        }

        logger.info("新增020订单使用配件入参:[{}]", JSON.toJSONString(dio));
        ResponseDTO response = maintenanceOrderUseModifyRemoteService.addMaintenanceOrderUse(dio);
        logger.info("新增020订单使用配件出参:[{}]", JSON.toJSONString(response));
        if (!response.isSuccess()) {
            throw new OmsBaseException("供应链服务：" + response.getMessage());
        }

        // 清空oms记录的配件
        this.clearOmsOrderPart(orderId);
    }


    /**
     * 清空OMS配件
     *
     * @param orderId
     */
    @Override
    public void clearOmsOrderPart(Long orderId) {
        // 1，删除工单配件
        orderPartService.deleteByOrderId(orderId);
        // 2，更新工单金额
        OrderWork orderWork = new OrderWork();
        orderWork.setOrderId(orderId);
        orderWork.setWorkId(orderId);
        orderWork.setPartUse(GlobalConsts.NO);
        orderWork.setPartRetain(GlobalConsts.NONE);
        orderWork.setPartAmount(0);
        orderWork.setInSourcingAmount(0);
        orderWork.setOutSourcingAmount(0);
        orderWork.setDeliverAmount(0);
        orderWork.setFactoryPartAmount(0);
        orderWork.setPartReimburseAmount(0);
        orderWork.setPartReimburse(GlobalConsts.NO);
        orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_NONE);
        orderWorkAmountBService.updatePartAmount(orderWork);
    }

    /**
     * 取消配件报销（外报、运杂）
     *
     * @param orderId
     * @param reimburseId
     * @return void
     * @author wangxiaokun
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearOrderPartByOrderIdAndReimburseId(Long orderId, String reimburseId) {
        List<OrderPart> orderParts = orderPartService.listByOrderIdAndReimburseIdSrcMaster(orderId, reimburseId);
        if (orderParts.isEmpty()) {
            return;
        }

        //查询主库
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, orderId);

        // 已派单&已领单&已上门&服务完成&已完成-进行中 不能取消外报和运杂
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT,
                OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE, OrderStatusConsts.WORK_STATUS_COMPLETE);
        boolean statusSupport = supportStatusList.contains(dbOrderWork.getStatus());
        if (!(statusSupport && Objects.equals(OrderStatusConsts.WORK_RESULT_DOING, dbOrderWork.getResultStatus()))) {
            logger.info("工单已收单不能取消外报或运杂，工单号:{}", dbOrderWork.getOrderId());
            return;
        }

        // 2. 删除工单配件
        orderPartService.deleteByOrderIdAndReimburseId(orderId, reimburseId);

        StringBuilder log = new StringBuilder();
        log.append("取消");

        //配件类型2外报，3运杂
        int partType = orderParts.get(0).getPartType();

        // 取消总金额
        int cancelAmount = orderParts.stream().mapToInt((e) -> MathUtil.amountMultiplyNumber(
                e.getPrice(), e.getNumber())).sum();

        boolean updatePartAmount = true;

        // 内采配件金额
        int outSourcingAmount = Optional.ofNullable(dbOrderWork.getOutSourcingAmount()).orElse(0);

        // 内采外报金额
        int inSourcingAmount = Optional.ofNullable(dbOrderWork.getInSourcingAmount()).orElse(0);

        // 订单杂项费用
        int deliverAmount = Optional.ofNullable(dbOrderWork.getDeliverAmount()).orElse(0);

        // 厂商配件金额
        int factoryPartAmount = Optional.ofNullable(dbOrderWork.getFactoryPartAmount()).orElse(0);

        // 外报配件
        if (Objects.equals(partType, OrderConsts.PART_TYPE_SOURCING_OUT)) {

            // 外报配件金额
            if (outSourcingAmount > 0) {
                outSourcingAmount -= cancelAmount;
            }

            log.append("外报配件：");
            log.append(orderParts.get(0).getMasterName());
            log.append("，总额：");
            log.append(MoneyUtil.parseToYuanStr(cancelAmount));
        } else if (Objects.equals(partType, OrderConsts.PART_TYPE_DELIVER)) {    // 运杂费

            // 运杂费金额
            if (deliverAmount > 0) {
                deliverAmount -= cancelAmount;
            }

            log.append("运杂费：");
            log.append(orderParts.get(0).getMasterName());
            log.append("，总额：");
            log.append(MoneyUtil.parseToYuanStr(cancelAmount));
        } else {
            updatePartAmount = false;
        }

        // 更新订单配件金额
        if (updatePartAmount) {

            // 配件总金额
            int partAmount = deliverAmount + inSourcingAmount + factoryPartAmount + outSourcingAmount;

            OrderWork orderWork = new OrderWork();
            orderWork.setOrderId(dbOrderWork.getOrderId());
            orderWork.setWorkId(dbOrderWork.getWorkId());
            if (partAmount == 0) {
                orderWork.setPartUse(GlobalConsts.NO);
                orderWork.setPartReimburse(GlobalConsts.NO);
                orderWork.setPartReimburseStatus(OrderConsts.PART_REIMBURSE_STATUS_NONE);
            } else {
                orderWork.setPartUse(GlobalConsts.YES);
            }

            orderWork.setPartRetain(GlobalConsts.NONE);
            orderWork.setPartAmount(partAmount);
            orderWork.setInSourcingAmount(inSourcingAmount);
            orderWork.setOutSourcingAmount(outSourcingAmount);
            orderWork.setDeliverAmount(deliverAmount);
            orderWork.setPartReimburseAmount(outSourcingAmount + deliverAmount);
            orderWorkAmountBService.updatePartAmount(orderWork);
        }

        orderParts.forEach(orderPart -> {
            log.append("\n");
            log.append(orderPart.getPartFullName());
            log.append(" 数量：");
            log.append(orderPart.getNumber());
            log.append(orderPart.getUnit());
            log.append(" 单价：");
            log.append(MoneyUtil.parseToYuanStr(orderPart.getPrice()));
            log.append(" 申报金额：");
            log.append(MoneyUtil.parseToYuanStr(orderPart.getDeclarePrice()));
        });

        //记录取消报销单号
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(dbOrderWork.getOrderId());
        orderLog.setWorkId(dbOrderWork.getWorkId());
        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_PART_DELETE_REIMBURSE);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_PART_DELETE_REIMBURSE));
        orderLog.setBeforeStatus(dbOrderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(dbOrderWork.getStatus()));
        orderLog.setBeforeResultStatus(dbOrderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(dbOrderWork.getResultStatus()));
        orderLog.setAfterStatus(dbOrderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(dbOrderWork.getStatus()));
        orderLog.setAfterResultStatus(dbOrderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(
                dbOrderWork.getResultStatus()));
        orderLog.setOperator(orderParts.get(0).getMasterName());
        orderLog.setOperatorId(orderParts.get(0).getMasterId().longValue());
        orderLog.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
        orderLog.setContent(log.toString());
        orderLogBService.save(orderLog);

    }

    @Override
    public void clearOrderInSourcingPart(Long orderId, Long operatorId, String operator) {
        List<OrderPart> orderParts = orderPartService.listByOrderId(orderId);
        if (orderParts.isEmpty()) {
            return;
        }

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);

        // 1. 退回工程师配件
        MaintenanceOrderUseDIO dio = new MaintenanceOrderUseDIO();
        dio.setWorkId(dbOrderWork.getWorkId());
        dio.setPlat(dbOrderWork.getPlatWork());
        dio.setStatus(GlobalConsts.NO);
        dio.setType(GlobalConsts.YES);
        dio.setGoodsTypes(OrderConsts.PART_TYPE_SOURCING_IN);
        dio.setOperator(operator);
        dio.setOperatorId(operatorId);

        logger.info("新增020订单使用配件入参:[{}]", JSON.toJSONString(dio));
        ResponseDTO response = maintenanceOrderUseModifyRemoteService.addMaintenanceOrderUse(dio);
        logger.info("新增020订单使用配件出参:[{}]", JSON.toJSONString(response));

        // 2. 删除工单配件
        orderPartService.deleteByOrderIdAndPartType(orderId, OrderConsts.PART_TYPE_SOURCING_IN);

        // 3. 更新配件金额
        // 总金额
        int partAmount = Optional.ofNullable(dbOrderWork.getDeliverAmount()).orElse(0) + Optional.ofNullable(dbOrderWork.getOutSourcingAmount()).orElse(0);
        OrderWork orderWork = new OrderWork();
        orderWork.setOrderId(dbOrderWork.getOrderId());
        orderWork.setWorkId(dbOrderWork.getWorkId());
        if (partAmount == 0) {
            orderWork.setPartUse(GlobalConsts.NO);
        } else {
            orderWork.setPartUse(GlobalConsts.YES);
        }
        orderWork.setPartRetain(GlobalConsts.NONE);
        orderWork.setPartAmount(partAmount);
        orderWork.setInSourcingAmount(0);
        orderWork.setOutSourcingAmount(dbOrderWork.getOutSourcingAmount());
        orderWork.setDeliverAmount(dbOrderWork.getDeliverAmount());
        orderWorkAmountBService.updatePartAmount(orderWork);
    }

    @Override
    public void clearInOrderPartByMasterIds(Long orderId, List<Integer> masterIdList, Long operatorId, String operator) throws OmsBaseException {
        List<OrderPart> orderParts = orderPartService.listByOrderIdSrcMaster(orderId, OrderConsts.PART_TYPE_SOURCING_IN);
        if (orderParts.isEmpty()) {
            return;
        }

        // 查找工程师是否有配件
        boolean isHasPart = orderParts.stream().anyMatch(item -> masterIdList.contains(item.getMasterId()));
        if (!isHasPart) {
            return;
        }

        List<OrderPart> masterOrderParts = orderParts.stream().filter(item -> !masterIdList.contains(item.getMasterId())).collect(Collectors.toList());
        AddOrderPartDTO addOrderPartDTO = new AddOrderPartDTO();
        addOrderPartDTO.setOrderId(orderId);
        addOrderPartDTO.setWorkId(orderId);
        addOrderPartDTO.setParts(masterOrderParts);
        addOrderPartDTO.setOperatorId(operatorId);
        addOrderPartDTO.setOperator(operator);
        this.insertInOrderPart(addOrderPartDTO);
    }

    @Override
    public List<OrderPart> listPartReimburseByOrderId(Long orderId) {
        List<OrderPart> orderPartList = orderPartService.listByOrderId(orderId);
        List<OrderPart> reimbursePartList = orderPartList.stream()
                .filter(part -> Objects.equals(GlobalConsts.YES, part.getReimburse()))
                .collect(Collectors.toList());
        return reimbursePartList;
    }

    @Override
    public void checkOrderGoodsIndicators(CheckOrderPartIndicatorsDTO dto) throws OmsBaseException {
        logger.info("校验工单配件指标 dto={}", dto);
//        Integer operatorType = Optional.ofNullable(dto.getOperatorType()).orElse(GlobalConsts.OPERATE_USER_TYPE_MASTER);

        if (CollectionUtil.isNullOrEmpty(dto.getOrderPartList())) {
            throw new OmsBaseException("配件数据为空");
        }

        List<OrderPart> orderPartList = dto.getOrderPartList();
        List<OrderGoodsDIO> goodsList = new ArrayList<>(orderPartList.size());
        for (OrderPart orderPart : orderPartList) {
            OrderGoodsDIO dio = new OrderGoodsDIO();
            dio.setGoodsId(orderPart.getPartId());
            dio.setNum(orderPart.getNumber());
            dio.setPrice(orderPart.getPrice());
            goodsList.add(dio);
        }

        logger.info("{} scmMonitorWarnListRemoteService.checkOrderGoodsIndicators goodsList={}", dto.getWorkId(), goodsList);
        ResponseDTO<CheckOrderDRO> responseDTO = scmMonitorWarnListRemoteService.checkOrderGoodsIndicators(dto.getWorkId(), dto.getPartType(), goodsList);
        logger.info("{} scmMonitorWarnListRemoteService.checkOrderGoodsIndicators responseDTO={}", dto.getWorkId(), responseDTO);
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getStatus(), responseDTO.getMessage());
        }
        CheckOrderDRO data = responseDTO.getData();
        if (!data.getFlag()) {
            throw new OmsBaseException(data.getGoodsIndicatorsContent());
        }
    }
}
